/**
 * 网络请求封装
 * 封装微信小程序请求，统一处理错误、鉴权等
 */

import config from './config';

// 服务器基础URL
const BASE_URL = config.apiBaseUrl;

// 请求队列，用于处理token刷新时的并发请求
let requestQueue = [];
let isRefreshing = false;

/**
 * 获取存储的token
 * @returns {string} token字符串
 */
function getToken() {
  return wx.getStorageSync(config.tokenKey) || '';
}

/**
 * 存储token
 * @param {string} token - 用户token
 */
function setToken(token) {
  wx.setStorageSync(config.tokenKey, token);
}

/**
 * 存储刷新token
 * @param {string} refreshToken - 刷新用的token
 */
function setRefreshToken(refreshToken) {
  wx.setStorageSync(config.refreshTokenKey, refreshToken);
}

/**
 * 获取刷新token
 * @returns {string} 刷新token
 */
function getRefreshToken() {
  return wx.getStorageSync(config.refreshTokenKey) || '';
}

/**
 * 输出调试信息
 * @param {...any} args - 调试信息参数
 */
function debug(...args) {
  if (config.debug) {
    console.log(...args);
  }
}

/**
 * 输出警告信息
 * @param {...any} args - 警告信息参数
 */
function warn(...args) {
  if (config.debug) {
    console.warn(...args);
  }
}

/**
 * 输出错误信息
 * @param {...any} args - 错误信息参数
 */
function error(...args) {
  if (config.debug) {
    console.error(...args);
  }
}

/**
 * 刷新token的方法
 * @returns {Promise} 返回刷新结果
 */
function refreshToken() {
  return new Promise((resolve, reject) => {
    wx.request({
      url: `${BASE_URL}/api/miniapp/auth/refresh-token`,
      method: 'POST',
      data: {
        refreshToken: getRefreshToken()
      },
      success: (res) => {
        if (res.statusCode === 200 && res.data.code === 0) {
          setToken(res.data.data.token);
          setRefreshToken(res.data.data.refreshToken);
          resolve(res.data.data.token);
        } else {
          // 刷新token失败，清除登录状态
          wx.removeStorageSync(config.tokenKey);
          wx.removeStorageSync(config.refreshTokenKey);
          wx.navigateTo({ url: '/pages/login/index' });
          reject(new Error('刷新token失败'));
        }
      },
      fail: (err) => {
        error('刷新token请求失败:', err);
        reject(err);
      }
    });
  });
}

/**
 * 发起网络请求的核心方法
 * @param {Object} options - 请求配置
 * @returns {Promise} 请求结果Promise
 */
function request(options) {
  const { url, method = 'GET', data = {}, headers = {} } = options;
  
  // 构建完整URL
  const fullUrl = url.startsWith('http') ? url : `${BASE_URL}${url}`;
  
  debug('请求信息:', {
    url: fullUrl,
    method,
    data,
    headers
  });
  
  // 设置请求头
  const token = getToken();
  const requestHeaders = {
    'Content-Type': 'application/json',
    ...headers
  };
  
  if (token) {
    requestHeaders['Authorization'] = `Bearer ${token}`;
  }
  
  return new Promise((resolve, reject) => {
    const requestTask = wx.request({
      url: fullUrl,
      method: method.toUpperCase(),
      data,
      header: requestHeaders,
      timeout: config.timeout,
      success: (res) => {
        debug('请求成功原始响应:', res);
        
        // 请求成功
        if (res.statusCode >= 200 && res.statusCode < 300) {
          resolve(res.data);
        } 
        // token失效
        else if (res.statusCode === 401) {
          debug('Token失效，准备刷新');
          const originalRequest = { ...options, resolve, reject };
          
          if (!isRefreshing) {
            isRefreshing = true;
            
            refreshToken().then(newToken => {
              debug('Token刷新成功，准备重试队列请求');
              // 重新执行队列中的请求
              requestQueue.forEach(req => {
                req.headers = req.headers || {};
                req.headers['Authorization'] = `Bearer ${newToken}`;
                request(req).then(req.resolve).catch(req.reject);
              });
              
              // 清空队列
              requestQueue = [];
              isRefreshing = false;
            }).catch(err => {
              error('刷新Token失败:', err);
              // 刷新失败，所有请求都失败
              requestQueue.forEach(req => {
                req.reject(err);
              });
              requestQueue = [];
              isRefreshing = false;
              reject(err);
            });
          }
          
          // 将请求加入队列
          debug('将请求加入队列等待Token刷新:', originalRequest);
          requestQueue.push(originalRequest);
        } 
        // 其他错误
        else {
          // 统一处理错误消息
          const errMsg = res.data?.message || '请求失败';
          error('请求失败:', errMsg, res);
          wx.showToast({
            title: errMsg,
            icon: 'none',
            duration: 2000
          });
          reject(new Error(errMsg));
        }
      },
      fail: (err) => {
        error('网络请求失败:', err);
        
        // 显示网络错误提示
        wx.showToast({
          title: '网络异常，请检查网络设置',
          icon: 'none',
          duration: 2000
        });
        reject(err);
      }
    });
    
    // 返回请求任务，支持中断请求
    return requestTask;
  });
}

export default request; 